[% setvar title Alternative array and hash slicing %]
<div id="archive-notice">
    <h3>This file is part of the Perl 6 Archive</h3>
    <p>To see what is currently happening visit <a href="http://www.perl6.org/">http://www.perl6.org/</a></p>
</div>
<div class='pod'>
<a name='TITLE'></a><h1>TITLE</h1>
<p>Alternative array and hash slicing</p>
<a name='VERSION'></a><h1>VERSION</h1>
<pre>  Maintainer: Mike Pastore &lt;<a href='mailto:pastorem@mediaone.net'>pastorem@mediaone.net</a>&gt;
  Date: 20 Aug 2000
  Mailing List: <a href='mailto:perl6-language@perl.org'>perl6-language@perl.org</a>
  Number: 134
  Version: 1
  Status: Developing</pre>
<a name='ABSTRACT'></a><h1>ABSTRACT</h1>
<p>This RFC attempts to address the confusion with regards to
taking a slice of a list or a hash. While most experienced
Perl hackers are on friendly terms with the current slicing
schema, ala:</p>
<pre>    $animals = [ 
        'dog', 'cat',
        'duck', 'cow',
        'pig', 'lizard' 
    ];
    
    $sounds  = { 
        dog  =&gt; 'bark', 
        cat  =&gt; 'meow', 
        duck =&gt; 'quack' 
    };
    
    @domestic = @{$sounds}{@{$animals}[0,1]};</pre>
<p>This is still difficult to look at, even for experienced
Perl hackers. While it can be grokked, it takes a good
amount of effort. Novice programmers and programmers coming
in from other languages have enormous difficulty
understanding these constructs.</p>
<a name='DESCRIPTION'></a><h1>DESCRIPTION</h1>
<p>Several alternatives (read: OPTIONAL) are being suggested
here as a means of taking a slice of a list (or a hash).</p>
<p>Ideally, one or more of these will be included in the
Perl 6 core as an alternative to the traditional deref-
and-slice syntax.</p>
<a name='Built-in Function slice()'></a><h2>Built-in Function <code>slice()</code></h2>
<p>Like the current built-in list function <code>splice()</code>,
<code>slice()</code> would take a list and slice parameters, and
return a slice.</p>
<pre>    @house_pets = slice(@$animals, [0..1]);</pre>
<p>Or, with a bit of Perl Magick, even dropping the redundant
dereference operation.</p>
<p>A major issue with <code>slice()</code> is the probable spelling
problem. Alternative function names would be lovely to
hear. :-)</p>
<a name='Quote-like Operator sl//ah'></a><h2>Quote-like Operator <code>sl//ah</code></h2>
<p>This may or may not make sense, but definitely looks
like a neat way to DWIM. The flags <code>a</code> and <code>h</code> indicate
an array or hash slice, respectively. Furthermore, use
of <code>[]</code> or <code>{}</code> containers also implies an array or hash
slice and circumvents the use of flags.</p>
<pre>    @livestock = (@$animals =~ sl/3..4/a);    # array slice
    @sounds = (values %$sounds =~ sl[1,3]);   # this too</pre>
<p>Please see <i>Slicing Extensions for Hashes</i> for more info
regarding hash slicing using this syntax.</p>
<a name='Arrow Notation (the infix dereference operator)'></a><h2>Arrow Notation (the infix dereference operator)</h2>
<p>An extension to arrow notation has also been suggested by
a number of people.</p>
<pre>    @domestic = $sounds-&gt;@{$animals-&gt;@[0,1]};</pre>
<p>Which is equivalent to the Perl 5 construct:</p>
<pre>    @domestic = @{$sounds}{@{$animals}[0,1]};</pre>
<p>As mentioned above. This syntax reads quite nicely from
left to right:</p>
<pre>    Dereference $sounds, taking the slice found by 
    dereferencing $animals and taking the slice of the
    first two elements.</pre>
<p>The biggest problem with this suggestion is the loss of
context. We are not returning one thingy from the
operation, but that is not obvious at first glance. The
eye (and mind) catches the <code>$</code> and moves on to the next
line. The plural context <code>@</code> is present but lost,
somewhere in the middle of the operation. This is a Bad
Thing. Therefore, the following is suggested, as a
parallel to the current arrow notation to get a single
thingy:</p>
<pre>    $thingy   = $animals-&gt;[0];      # evaluates to:
    $thingy   = ${$animals}[0];

    @thingies = @$animals-&gt;[0..2];  # evaluates to:
    @thingies = @{$animals}[0..2];</pre>
<p>Unfortunately, this opens up a whole new can of worms
that has been covered before in p5p and should be covered
again (see REFERENCES). But not in this RFC.</p>
<p>One more alternative: context sensitivity.</p>
<pre>    $num_thingies = $animals-&gt;[1..3];
    @thingies     = $animals-&gt;[1..3];</pre>
<a name='Slicing Extensions for Hashes'></a><h2>Slicing Extensions for Hashes</h2>
<p>The ability to take an <i>indexed</i> slice of a hash is
desired. This would allow the programmer to pare out
several keys and values from hash A into a new hash B, for
greatest flexibility. Currently, this is only available
through <code>map()</code>:</p>
<pre>    %other = map { $_ =&gt; $sounds-&gt;{$_} } qw(lizard duck);</pre>
<p>Which could be simplified to:</p>
<pre>    %other = slice(%$sounds, { qw(lizard duck) }); # or,
    %other = (%$sounds =~ sl/lizard duck/h);       # or,
    %other = %$sounds-&gt;{'lizard', 'duck'};         # or,
    %other = %{$sounds}{ qw(lizard duck) };        # trad'l</pre>
<p>Furthermore:</p>
<pre>    %hash = slice(%$sounds, ['dog']);  # dies (%+[] usage)
    %hash = %$sounds =~ sl[dog];       # same as above
    @list = slice(@$animals, {0..1});  # dies (@+{} usage)
    @list = @$animals =~ sl{0..1};     # same as above</pre>
<p>Which will promote proper coordination between <code>@</code> and
<code>[]</code>, and between <code>%</code> and <code>{}</code>. This allows for an
easier transition from the built-in <code>slice()</code> to the more
traditional approaches.</p>
<p>Finally, flattened indexed slices and hash value slicing.</p>
<pre>    @foo = %{$sounds}{'dog', 'duck'};          # flatten
    @foo = slice(%$sounds, {'dog', 'duck'});   # to list
    
    @bar = @{$sounds}{'dog', 'lizard'};        # retrieve
    @bar = slice(@$sounds, {'dog', 'lizard'}); # values 
    @bar = slice(values %$sounds, [0,2]);      # only</pre>
<a name='SUMMARY'></a><h1>SUMMARY</h1>
<p>To pull this together, the following should just DWIM:</p>
<pre>    $foo = 'thingy';
    @bar = qw(atomic whutzits galore);
    %zot = (tree=&gt;'wood', rock=&gt;'stone', pond=&gt;'water');

    $foo_ref = \$foo; $bar_ref = \@bar; $zot_ref = \%zot;
    
    # ($) singular context                   #
    $thingy = $foo;                          #
    $thingy = ${$foo_ref}                    # 
    $thingy = $bar[0];                       # or,
    $thingy = ${$bar_ref}[0];                # 
    $thingy = $zot{'tree'};                  # or,
    $thingy = ${$zot_ref}{'tree'};           #   

    # (@) plural context                     #
    @whutzits = @bar[1..2];                  # or, 
    @whutzits = @{$bar_ref}[1..2];           #
    @whutzits = @zot{'tree', 'rock'};        # or,
    @whutzits = @{$zot_ref}{'tree', 'rock'}; #

    # (%) indexed context                    #
    %flimmers = %zot{'pond', 'rock'};        # or,
    %flimmers = %{$zot_ref}{'pond', 'rock'}; #
    </pre>
<p>Extending and allowing, of course, for all of the new
syntaxes listed above:</p>
<pre>    $thingy   = $zot_ref-&gt;{'tree'};
    @whutzits = @$bar_ref-&gt;[0..2];
    @atomics  = @$zot_ref =~ sl{'tree', 'rock'};
    %flimmers = slice(%$zot_ref, {'pond', 'rock'});</pre>
<a name='IMPLEMENTATION'></a><h1>IMPLEMENTATION</h1>
<p>Could get ugly.</p>
<p>Ah ain't knowing no C, paw.</p>
<a name='REFERENCES'></a><h1>REFERENCES</h1>
<p>RFC 109: Less line noise - let's get rid of @%</p>
<p>Forthcoming RFC from this author: Against RFC 109</p>
<p>Forthcoming RFC from Nathan Wiger: Reference Variables</p>
<p>Perl 5 Porters, May-June 1998
<a href='http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/' target='_blank'>www.xray.mpe.mpg.de</a></p>
</div>
